home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / windows / winterm / asdriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-01  |  11.3 KB  |  450 lines

  1. /*      --- asDriver.c  V1.0 Jan 1994 (windows version) ---
  2. **
  3. **  ASCII driver.
  4. **
  5. **  Copyright(C) 1994 by MarshallSoft Computing, Inc.
  6. **  All rights are reserved.
  7. */
  8.  
  9. #define DEBUG 0
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include "windows.h"
  14. #include "pcl4w.h"
  15. #include "ascodes.h"
  16. #include "errcodes.h"
  17. #include "ascii.h"
  18. #include "asdriver.h"
  19. #include "term_io.h"
  20. #include "file_io.h"
  21. #include "paint.h"
  22. #include "info.h"
  23. #include "dir_io.h"
  24.  
  25. extern HWND hMainWnd;
  26. extern HWND hInfoWnd;
  27.  
  28. /*** ascDriver functions & variables */
  29.  
  30. long FileLength(int);             /* returns file length */
  31. static char Temp[255];            /* temporary buffer */
  32. static void XOFF_Test(int);
  33. static void XON_Test(int);
  34.  
  35. #define BUFFER_SIZE 1000
  36.  
  37. /*** ascDriver state variables ***/
  38.  
  39. static int  ascActive=FALSE;        /* TRUE if initialized */
  40. static char ascBuffer[BUFFER_SIZE+1]; /* data packet buffer */
  41. static int  ascBufferSize;          /* # bytes in ascBuffer */
  42. static int  ascBufferIndex;         /* index to next char */
  43. static long ascCharCount;           /* # chars sent or received */
  44. static int  ascErrorCode;           /* last error code */
  45. static int  ascErrorState;          /* state in which last error occured */
  46. static char ascFilename[64];        /* filename */
  47. static long ascFileSize;            /* file size */
  48. static char ascFileSpec[64];        /* current file specification */
  49. static int  ascHandle;              /* file Handle */
  50. static int  ascPort;                /* serial port */
  51. static int  ascState;               /* current driver state */
  52. static int  ascLastState;           /* last driver state */
  53. static int  ascStateCount;          /* # times last state called */
  54. static int  ascCharPace;            /* ms delay after sending each char */
  55. static char ascTermChar;            /* termination char ( 0x00 => none) */
  56. static int  ascEchoFlag;            /* echo flag */
  57. static int  ascLastXchar;           /* last XON/XOFF received */
  58. static long ascMarkTime;            /* time last char received */
  59. static long ascSendTime;            /* time to send next char */
  60. static int  ascLowWater;            /* RX buffer low water mark */
  61. static int  ascHighWater;           /* RX buffer high water mark */
  62. static int  ascMaxBurst;            /* # chars to send in burst */
  63.  
  64. static char *XONptr  = "XON    ";
  65. static char *XOFFptr = "XOFF   ";
  66.  
  67. int SetASCerror(int);
  68.  
  69. /*** ascDriver functions ***/
  70.  
  71. int ascAbort(void)
  72. {int i;
  73.  DisplayLine("Aborting...");
  74.  ascErrorCode = NO_ERROR;
  75.  ascErrorState = 0;
  76.  ascState = ASC_IDLE;
  77.  for(i=0;i<6;i++) if(PutChar(ascPort,CAN)==-1) break;
  78.  SioRxFlush(ascPort);
  79.  return(0);
  80. }
  81.  
  82. int ascGetErrorCode(void)
  83. {
  84.  ascDriver();
  85.  return( ascErrorCode );
  86. }
  87.  
  88. int ascGetErrorState(void)
  89. {
  90.  ascDriver();
  91.  return( ascErrorState );
  92. }
  93.  
  94. char *ascGetFilename(void)
  95. {
  96.  ascDriver();
  97.  return( ascFilename );
  98. }
  99.  
  100. int ascGetState(void)
  101. {
  102.  ascDriver();
  103.  return( ascState );
  104. }
  105.  
  106. long ascGetFileLength()
  107. {
  108.  ascDriver();
  109.  return( ascFileSize );
  110. }
  111.  
  112. long ascGetCharCount()
  113. {
  114.  ascDriver();
  115.  return( ascCharCount );
  116. }
  117.  
  118. int ascInit(Port)
  119. int Port;
  120. {
  121. #if DEBUG
  122.  sprintf(Temp,"ascInit: Port=COM%d",Port+1);
  123.  DisplayLine(Temp);
  124.  ascLastState = -1;
  125.  ascStateCount = 0;
  126. #endif
  127.  ascActive = TRUE;
  128.  ascPort = Port;
  129.  ascState = ASC_IDLE;
  130.  ascHandle = -1;
  131.  ascFilename[0] = '\0';
  132.  ascErrorCode = NO_ERROR;
  133.  return(0);
  134. }
  135.  
  136. int ascStartTx(char *Filename,     /* File name */
  137.                int  CharPace,      /* char pace in ms */
  138.                char TermChar,      /* termination char */
  139.                int  EchoFlag)      /* echo flag */
  140. {
  141. #if DEBUG
  142.  sprintf(Temp,"ascStartTx:Filename='%s' TermChar='%c' EchoFlag=%d",
  143.    Filename,TermChar,EchoFlag);
  144.  DisplayLine(Temp);
  145. #endif
  146.  ascErrorCode = NO_ERROR;
  147.  ascErrorState = 0;
  148.  strcpy(ascFileSpec,Filename);
  149.  ascState = TX_START;
  150.  ascFileSize = 0;
  151.  ascCharPace = CharPace;
  152.  if(ascCharPace<5) ascCharPace = 5;
  153.  ascMaxBurst = 250 / ascCharPace;
  154.  ascTermChar = TermChar;
  155.  ascEchoFlag = EchoFlag;
  156.  ascLastXchar = XON;
  157.  ascCharCount = 0L;
  158.  ascDriver();
  159.  return(0);
  160. } /* ascStartTx */
  161.  
  162. int ascStartRx(char *Filename,     /* File name */
  163.                int  RxQueSize,     /* RX queue size */
  164.                char TermChar,      /* termination char */
  165.                int  EchoFlag)      /* echo flag */
  166. {
  167. #if DEBUG
  168.  sprintf(Temp,"ascStartRx:Filename='%s' RxQueSize=%d TermChar='%c' EchoFlag=%d",
  169.    Filename,RxQueSize,TermChar,EchoFlag);
  170.  DisplayLine(Temp);
  171. #endif
  172.  ascErrorCode = NO_ERROR;
  173.  ascErrorState = 0;
  174.  strcpy(ascFilename,Filename);
  175.  ascState = RX_START;
  176.  ascFileSize = 0;
  177.  ascLowWater = RxQueSize / 4;
  178.  ascHighWater = RxQueSize / 2;
  179.  ascTermChar = TermChar;
  180.  ascEchoFlag = EchoFlag;
  181.  ascLastXchar = XON;
  182.  ascCharCount = 0L;
  183.  ascDriver();
  184.  return(0);
  185. } /* end ascStartRx */
  186.  
  187. int ascDriver()
  188. {int i, n;
  189.  char c;
  190.  char *Ptr;
  191.  int Code;          /* return code */
  192.  /* start */
  193.  if(!ascActive)
  194.    {SetASCerror(NOT_ACTIVE_ERROR);
  195.     return(TRUE);
  196.    }
  197. #if DEBUG
  198.  if(ascLastState!=ascState)
  199.    {sprintf(Temp,"%ld: State = %d ",GetTickCount(),ascState);
  200.     DisplayLine(Temp);
  201.    }
  202. #endif
  203.  if(ascLastState==ascState) ascStateCount++;
  204.  else
  205.    {ascStateCount = 1;
  206.     ascLastState = ascState;
  207.    }
  208.  /* process according to state */
  209.  switch(ascState)
  210.    {
  211.  
  212.     case ASC_IDLE:
  213.  
  214.       /* return TRUE for IDLE */
  215.       return( TRUE );
  216.  
  217.     /*** Transmit states ***/
  218.  
  219.     case TX_START:
  220.  
  221.       if(FindFirst(&ascFileSpec[0],&ascFilename[0]))
  222.         {/* got match ! */
  223.          ascState = TX_NEWFILE;
  224.         }
  225.       else
  226.         {/* no file found */
  227.          SetASCerror(NO_SUCH_FILE_ERROR);
  228.         }
  229.       break;
  230.  
  231.     case TX_NEWFILE:
  232.  
  233.       ascHandle = _lopen(&ascFilename[0],OF_READ|OF_SHARE_DENY_WRITE);
  234.       if(ascHandle<0)
  235.          {SetASCerror(CANNOT_OPEN_ERROR);
  236.           break;
  237.          }
  238.       ascFileSize = FileLength(ascHandle);
  239.       /* clear comm port */
  240.       SioRxFlush(ascPort);
  241.       ascState = TX_READ_DISK;
  242.       break;
  243.  
  244.     case TX_READ_DISK:
  245.  
  246.       /* read next block from disk */
  247.       Code = _lread(ascHandle,ascBuffer,BUFFER_SIZE);
  248.       if(Code<0)
  249.         {SetASCerror(DISK_READ_ERROR);
  250.          break;
  251.         }
  252.       if(Code==0) ascState = TX_DONE;
  253.       else
  254.         {ascBufferSize = Code;
  255.          ascBufferIndex = 0;
  256.          ascState = TX_WAIT4_XON;
  257.         }
  258.       break;
  259.  
  260.     case TX_WAIT4_XON:
  261.  
  262.       if(ascLastXchar==XOFF)
  263.         {
  264.          Code = GetChar(ascPort);
  265.          if((char)Code==XON)
  266.            {ascLastXchar = XON;
  267.             ascState = TX_SEND_DATA;
  268.             InfoStatus(XONptr);
  269.             SendMessage(hInfoWnd,WM_USER,0,0L);
  270.             break;
  271.            }
  272.          if((char)Code==CAN)
  273.           {ascState = ASC_IDLE;
  274.            break;
  275.           }
  276.         }
  277.       else ascState = TX_SEND_DATA;
  278.       break;
  279.  
  280.     case TX_SEND_DATA:
  281.  
  282.       /* send burst */
  283.       n = min(ascMaxBurst,ascBufferSize-ascBufferIndex);
  284.       if(n>0)
  285.         {/* send byte(s) */
  286.          if(ascEchoFlag) WriteTheString(&ascBuffer[ascBufferIndex],n);
  287.          for(i=0;i<n;i++) Code = PutChar(ascPort,ascBuffer[ascBufferIndex++]);
  288.          ascCharCount = ascCharCount + n;
  289.         }
  290.       /* buffer empty ? */
  291.       if(ascBufferIndex==ascBufferSize) ascState = TX_READ_DISK;
  292.       else
  293.         {ascSendTime = GetTickCount() + (long)ascCharPace;
  294.          ascState = TX_PACE;
  295.         }
  296.       /* check for incoming XON or XOFF */
  297.       Code = GetChar(ascPort);
  298.       if(((char)Code==XON)&&(ascLastXchar==XOFF))
  299.          {ascLastXchar = (char)XON;
  300.           InfoStatus(XONptr);
  301.           SendMessage(hInfoWnd,WM_USER,0,0L);
  302.          }
  303.       if(((char)Code==XOFF)&&(ascLastXchar==XON))
  304.          {ascLastXchar = (char)XOFF;
  305.           InfoStatus(XOFFptr);
  306.           SendMessage(hInfoWnd,WM_USER,0,0L);
  307.          }
  308.       break;
  309.  
  310.     case TX_PACE:
  311.  
  312.       if(GetTickCount() < ascSendTime) break;
  313.       ascState = TX_WAIT4_XON;
  314.       break;
  315.  
  316.     case TX_DONE:
  317.  
  318.       if(ascTermChar) PutChar(ascPort,ascTermChar);
  319.       _lclose(ascHandle);
  320.       ascState = ASC_IDLE;
  321.       break;
  322.  
  323.      /*** Receive states ***/
  324.  
  325.     case RX_START:
  326.  
  327.       /* clear comm port */
  328.       SioRxFlush(ascPort);
  329.       ascState = RX_OPEN_FILE;
  330.       break;
  331.  
  332.     case RX_OPEN_FILE:
  333.  
  334.       /* open file passed in Filename[] for write */
  335.       ascHandle = _lcreat(&ascFilename[0],0);
  336.       if(ascHandle<0)
  337.         {SetASCerror(CANNOT_OPEN_ERROR);
  338.          break;
  339.         }
  340.       ascMarkTime = GetTickCount();
  341.       ascBufferIndex = 0;
  342.       ascState = RX_GET_DATA;
  343.       break;
  344.  
  345.     case RX_GET_DATA:
  346.  
  347.       XON_Test(ascLowWater);
  348.       n = 0; Ptr = &ascBuffer[ascBufferIndex];
  349.       /* gather up line */
  350.       for(i=0;i<82;i++)
  351.         {Code = GetChar(ascPort);
  352.          if(Code==-1)
  353.            {/* byte not ready */
  354.             if(GetTickCount() > ascMarkTime + (long)TEN_SECS) ascState = RX_DONE;
  355.             break;
  356.            }
  357.          /* received char */
  358.          if((char)Code==ascTermChar)
  359.            {ascState = RX_DONE;
  360.             break;
  361.            }
  362.          if((char)Code==CAN)
  363.            {DisplayLine("Cancelled by sender");
  364.             ascState = RX_DONE;
  365.             break;
  366.            }
  367.          /* save data in buffer */
  368.          c = (char)Code;
  369.          ascBuffer[ascBufferIndex++] = c;
  370.          ascCharCount++; n++;
  371.          if(ascBufferIndex>=BUFFER_SIZE)
  372.            {ascState = RX_WRITE_DISK;
  373.             break;
  374.            }
  375.          else ascMarkTime = GetTickCount();
  376.         } /* end for(i) */
  377.       if(ascEchoFlag && (n>0)) WriteTheString(Ptr,n);
  378.       XOFF_Test(ascHighWater);
  379.       break;
  380.  
  381.    case RX_WRITE_DISK:
  382.  
  383.       XOFF_Test(0);
  384.       /* write Buffer to disk */
  385.       _lwrite(ascHandle,ascBuffer,ascBufferIndex);
  386.       ascBufferIndex = 0;
  387.       ascMarkTime = GetTickCount();
  388.       ascState = RX_GET_DATA;
  389.       break;
  390.  
  391.     case RX_DONE:
  392.  
  393.       if(ascBufferIndex) _lwrite(ascHandle,ascBuffer,ascBufferIndex);
  394.       _lclose(ascHandle);
  395.       ascState = ASC_IDLE;
  396.       break;
  397.  
  398.     default:
  399.  
  400.        sprintf(Temp,"INTERNAL ERROR: Bad state = %d",ascState);
  401.        DisplayLine(Temp);
  402.        SetASCerror(INTERNAL_ERROR);
  403.        break;
  404.    } /* end switch */
  405.  return(FALSE);
  406. } /* end ascDriver */
  407.  
  408. int SetASCerror(int Code)
  409. {int i;
  410.  ascErrorCode = Code;
  411.  ascErrorState = ascState;
  412.  ascState = ASC_IDLE;
  413.  if(Code!=NO_ERROR) for(i=0;i<6;i++) PutChar(ascPort,CAN);
  414.  SioRxFlush(ascPort);
  415.  if(Code)
  416.    {sprintf(Temp,"ascDriver: Error=%d ascLastState=%d ascStateCount=%d",
  417.      Code,ascLastState,ascStateCount);
  418.     DisplayLine(Temp);
  419.    }
  420.  return(Code);
  421. } /* end SetASCerror */
  422.  
  423. void XON_Test(int LowWater)
  424. {int RxQueSize;
  425.  /* do we need to send XON ? */
  426.  if(ascLastXchar==XOFF)
  427.    {RxQueSize = SioRxQue(ascPort);
  428.     if(RxQueSize <= LowWater)
  429.       {PutChar(ascPort,(char)XON);
  430.        ascLastXchar = XON;
  431.        InfoStatus(XONptr);
  432.        SendMessage(hInfoWnd,WM_USER,0,0L);
  433.       }
  434.    }
  435. } /* end XON_Test */
  436.  
  437. void XOFF_Test(int HighWater)
  438. {int RxQueSize;
  439.  /* do we need to send XOFF ? */
  440.  if(ascLastXchar==XON)
  441.    {RxQueSize = SioRxQue(ascPort);
  442.     if(RxQueSize >= HighWater)
  443.       {PutChar(ascPort,(char)XOFF);
  444.        ascLastXchar = XOFF;
  445.        InfoStatus(XOFFptr);
  446.        SendMessage(hInfoWnd,WM_USER,0,0L);
  447.       }
  448.    }
  449. } /* end XOFF_Test */
  450.